package org.dt.common.sequence.spring;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.dt.common.sequence.BaseDelegator;
import org.dt.common.sequence.CasDelegator;
import org.dt.common.sequence.SequenceHolder;
import org.dt.common.sequence.SequenceHolderFactory;
import org.dt.common.sequence.config.SeqHolderConfig;
import org.dt.common.sequence.config.SeqHolderSpec;
import org.dt.common.sequence.persist.CasSeqMapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.Map;
import java.util.concurrent.Executor;

/**
 * @author: yujiadong
 * @create: 2019/01/09 17:39
 **/
@EnableConfigurationProperties({SeqManagerProperties.class})
public abstract class BaseSeqManagerConfiguration implements InitializingBean, ApplicationContextAware {
    private ApplicationContext   context;
    private SeqManagerProperties properties;

    @Bean("seqHolderExecutor")
    public ThreadPoolTaskExecutor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor     = new ThreadPoolTaskExecutor();
        int                    corePoolSize = Runtime.getRuntime().availableProcessors();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(corePoolSize);
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setThreadNamePrefix("SeqHolderExecutor-");
        executor.initialize();
        return executor;
    }

    @Bean
    public SeqHolderConfig seqHolderConfig() throws IllegalAccessException {
        SeqHolderConfig config = new SeqHolderConfig();

        for (Map.Entry<String, SeqProperties> entry : properties.getBiz().entrySet()) {
            String        biz  = entry.getKey();
            SeqProperties prop = entry.getValue();
            SeqHolderSpec spec = SeqHolderSpec.parse(prop.getSpec());
            config.getSpecs().put(biz, spec);
            config.getTypes().put(biz, prop.getType());
        }
        return config;
    }

    @Bean
    public SequenceHolderFactory sequenceHolderFactory(SeqHolderConfig seqHolderConfig, BaseDelegator delegator, Executor seqHolderExecutor) {
        return new SequenceHolderFactory(seqHolderConfig, delegator, seqHolderExecutor);
    }

    @Override
    public void afterPropertiesSet() {
        properties = context.getBean(SeqManagerProperties.class);
        Validate.isTrue(properties.getBiz() != null && properties.getBiz().keySet().stream().allMatch(StringUtils::isNotBlank),
                        "biz不能空，请检查配置文件中是否存在cathay.sequence.biz.{biz-name}项");
    }

    @Bean
    public abstract CasDelegator delegator(CasSeqMapper mapper);

    @Bean
    public abstract SequenceHolder sequenceHolder(SequenceHolderFactory sequenceHolderFactory);

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

//	@Bean
//	public TransactionDelegator transactionDelegator(PolicyTransactionSeqMapper mapper) {
//		Validate.notNull(mapper);
//		return new TransactionDelegator(mapper);
//	}

}
